package com.wayneleo.launcher.core;

import com.wayneleo.launcher.api.LauncherModule;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

class ModuleLoader {
    private static final Logger LOG = Logger.getLogger(ModuleLoader.class.getName());
    private static List<LauncherModule> modules = null;

    private ModuleLoader() {
    }

    static void destroyModules() {
        try {
            LOG.info("destroying modules");
            if (null == modules) {
                return;
            }
            for (LauncherModule module : modules) {
                if (null == module) {
                    continue;
                }
                module.shutdown(LauncherContext.getInstance());
            }
        } catch (Exception e) {
            throw new LoadModuleException(e);
        }
    }

    static void initModules(String... args) {
        try {
            LOG.info("loading modules");
            LauncherContext context = LauncherContext.getInstance();
            modules = findModules(context.getBinDir() + File.separator + context.getModuleConfFilename());
            if (modules.size() < 1) {
                LOG.warning("Not found any module!!");
                return;
            }
            for (LauncherModule module : modules) {
                if (null == module) {
                    continue;
                }
                module.startup(LauncherContext.getInstance(), args);
            }
        } catch (Exception e) {
            throw new LoadModuleException(e);
        }
    }

    /**
     * 返回所有模块的集合
     *
     * @return 所有模块的集合
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    private static List<LauncherModule> findModules(final String modulesFilename) throws IOException {
        // 获取配置文件
        File modulesFile = open(modulesFilename);
        // 读取文件内容
        List<ModuleInfo> moduleInfos = read(modulesFile);
        // 解析文件内容,构建模块信息
        List<LauncherModule> modules = parse(moduleInfos);
        // 结果集,从配置文件中读取的所有模块
        /*-
         * 文件存在
         */
        if (!modulesFile.exists() || !modulesFile.isFile()) {
            LOG.warning("Configuration is not found : " + modulesFilename);
            return new ArrayList<>();
        }
        if (!modules.isEmpty()) {
            return modules;
        }
        return new ArrayList<>();
    }

    @SuppressWarnings("unchecked")
    private static List<LauncherModule> parse(final List<ModuleInfo> moduleInfos) {
        List<LauncherModule> modules = new ArrayList<>();
        if (null == moduleInfos) {
            return new ArrayList<>();
        }
        Class<?> clazz;
        Class<? extends LauncherModule> moduleClass;
        Class<LauncherModule> lmc = LauncherModule.class;
        for (ModuleInfo moduleInfo : moduleInfos) {
            try {
                clazz = Class.forName(moduleInfo.className);
                if (!lmc.isAssignableFrom(clazz)) {
                    continue;
                }
                moduleClass = (Class<? extends LauncherModule>) clazz;
                modules.add(moduleClass.newInstance());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                throw new LoadModuleException(e);
            }
        }
        return modules;
    }

    private static List<ModuleInfo> read(final File modulesFile) throws IOException {
        List<ModuleInfo> moduleInfos = new ArrayList<>();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(modulesFile));
            String tmp;
            ModuleInfo moduleInfo;
            while (null != (tmp = reader.readLine())) {
                moduleInfo = new ModuleInfo(tmp, 0);
                moduleInfos.add(moduleInfo);
            }
        } finally {
            if (null != reader) {
                reader.close();
            }
        }
        return moduleInfos;
    }

    private static File open(final String modulesFilename) {
        // 模块配置文件的File对象
        File modulesFile = new File(modulesFilename);
        if (!modulesFile.exists()) {
            throw new LoadModuleException("Do not found modules configuration file : " + modulesFilename);
        }
        if (!modulesFile.isFile()) {
            throw new LoadModuleException(modulesFilename + " is not a file");
        }
        return modulesFile;
    }
}
